home *** CD-ROM | disk | FTP | other *** search
- Subject: v20i073: Pcomm telecommunication package, Part07/08
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: fthood!egray
- Posting-number: Volume 20, Issue 73
- Archive-name: pcomm1.2/part07
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # terminal.c
- # tty_att.c
- # tty_ucb.c
- # vcs.c
- # vcs.h
- # waitfor.c
- # x_ascii.c
- # x_batch.c
- # x_extrnl.c
- export PATH; PATH=/bin:/usr/bin:$PATH
- echo shar: "extracting 'terminal.c'" '(9863 characters)'
- if test -f 'terminal.c'
- then
- echo shar: "will not over-write existing file 'terminal.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'terminal.c'
- X/*
- X * Start the terminal dialogue, fork the input routine, watch for the
- X * hot key so we can execute an option.
- X */
- X
- X#include <stdio.h>
- X#include <curses.h>
- X#include <signal.h>
- X#include "config.h"
- X#include "dial_dir.h"
- X#include "misc.h"
- X#include "modem.h"
- X#include "param.h"
- X#include "status.h"
- X#include "xmodem.h"
- X
- X#ifdef UNIXPC
- X#include <sys/phone.h>
- X#include <fcntl.h>
- X#endif /* UNIXPC */
- X
- Xstatic int pid = -1;
- X
- Xterminal(extra_dir, input_status)
- Xchar *extra_dir;
- Xint input_status;
- X{
- X extern int fd;
- X int i, j, k, cr_lf, script;
- X char c, lf=10, *str_rep(), *keymac, *memset();
- X void help_screen(), line_set(), n_shell(), load_vs(), send_str();
- X void release_port(), do_input(), list_dir(), pexit(), zap_vs();
- X void st_line(), chg_dir(), screen_dump(), input_off(), suspend();
- X void info(), term_mode(), macro(), do_script();
- X
- X /* if starting out in command mode */
- X if (!input_status) {
- X erase();
- X refresh();
- X st_line("");
- X }
- X /* put stdin/stdout in terminal mode */
- X resetterm();
- X term_mode();
- X cr_lf = !strcmp(param->cr_out, "CR/LF");
- X
- X if (input_status) {
- X do_script(extra_dir);
- X do_input();
- X }
- X
- X while (1) {
- X read(0, &c, 1);
- X c &= 0x7f;
- X /* is it the hot key? */
- X if (c == param->hot) {
- X /* suspend input */
- X input_status = 0;
- X suspend(TRUE);
- X script = 0;
- X
- X /*
- X * Put the terminal in the curses mode, load the
- X * virtual screen and add the status line at the bottom.
- X */
- X fixterm();
- X load_vs();
- X st_line("");
- X#ifndef OLDCURSES
- X keypad(stdscr, TRUE);
- X#endif /* OLDCURSES */
- X i = wgetch(stdscr);
- X /* map an additional hot key to -1 */
- X if (i == param->hot)
- X i = -1;
- X
- X keymac = "";
- X /* look for options */
- X k = -1;
- X switch (i) {
- X case -1: /* 2 "hots" means send 1 */
- X k = param->hot;
- X break;
- X case '0': /* help screen */
- X help_screen(param->ascii_hot);
- X break;
- X case 'd':
- X case 'D': /* dialing directory */
- X if (dial_menu())
- X input_status = dial_win();
- X script = input_status;
- X break;
- X case 'r':
- X case 'R': /* redial */
- X if (redial())
- X input_status = dial_win();
- X script = input_status;
- X break;
- X case 'm':
- X case 'M': /* keyboard macros */
- X macro();
- X break;
- X case 'p':
- X case 'P': /* line settings */
- X if (ls_menu())
- X line_set();
- X break;
- X case 'x':
- X case 'X': /* exit */
- X pexit();
- X break;
- X case '4': /* Unix gateway */
- X n_shell();
- X break;
- X case 'i':
- X case 'I': /* program info screen */
- X info(MANUAL_CLEAR);
- X break;
- X case 's': /* setup menu */
- X case 'S':
- X input_status = setup_menu();
- X break;
- X case 'c': /* clear the screen */
- X case 'C':
- X zap_vs();
- X erase();
- X#ifdef SHAREDMEM
- X if (pid == -1) {
- X for (j=0; j<LINES; j++)
- X memset(status->vs[j], ' ', COLS);
- X }
- X#endif /* SHAREDMEM */
- X break;
- X case 'b':
- X case 'B': /* change directory */
- X chg_dir();
- X break;
- X case 'e':
- X case 'E': /* toggle duplex */
- X if (dir->duplex[dir->d_cur] == 'F')
- X dir->duplex[dir->d_cur] = 'H';
- X else
- X dir->duplex[dir->d_cur] = 'F';
- X
- X /* show changes */
- X st_line("");
- X k = wait_key(stdscr, 2);
- X break;
- X case 'h':
- X case 'H': /* hang up phone */
- X release_port(VERBOSE);
- X input_off();
- X break;
- X case 'l':
- X case 'L': /* toggle printer */
- X status->print = status->print ? 0 : 1;
- X#ifndef SHAREDMEM
- X if (pid != -1)
- X kill(pid, SIGUSR2);
- X#endif /* SHAREDMEM */
- X /* show changes */
- X st_line("");
- X k = wait_key(stdscr, 2);
- X break;
- X case '3': /* toggle CR - CR/LF */
- X if (!strcmp(param->cr_in, "CR")) {
- X param->cr_in = str_rep(param->cr_in, "CR/LF");
- X status->add_lf = 1;
- X }
- X else {
- X param->cr_in = str_rep(param->cr_in, "CR");
- X status->add_lf = 0;
- X }
- X#ifndef SHAREDMEM
- X input_off();
- X input_status++;
- X#endif /* SHAREDMEM */
- X /* show changes */
- X st_line("");
- X k = wait_key(stdscr, 2);
- X break;
- X case '7': /* break key */
- X if (fd != -1)
- X tty_break(fd);
- X
- X st_line(" break");
- X break;
- X#ifndef OLDCURSES
- X case KEY_UP:
- X#endif /* OLDCURSES */
- X case 'u':
- X case 'U': /* send files */
- X input_status = xfer_menu(UP_LOAD);
- X break;
- X#ifndef OLDCURSES
- X case KEY_DOWN:
- X case '\n':
- X#endif /* OLDCURSES */
- X case 'n':
- X case 'N': /* receive files */
- X input_status = xfer_menu(DOWN_LOAD);
- X break;
- X case 't':
- X case 'T':
- X input_status = pass_thru();
- X break;
- X case 'f':
- X case 'F': /* list directory */
- X list_dir();
- X break;
- X case 'g': /* screen dump */
- X case 'G':
- X screen_dump();
- X st_line(" screen dump");
- X k = wait_key(stdscr, 2);
- X break;
- X case '1': /* data logging */
- X input_status = data_logging();
- X break;
- X case '2': /* toggle log */
- X if (!strcmp(status->log_path, "NOT_DEFINED")) {
- X beep();
- X st_line(" no log file");
- X k = wait_key(stdscr, 2);
- X break;
- X }
- X status->log = status->log ? 0 : 1;
- X#ifndef SHAREDMEM
- X if (pid != -1)
- X kill(pid, SIGUSR1);
- X#endif /* SHAREDMEM */
- X /* show changes */
- X st_line("");
- X k = wait_key(stdscr, 2);
- X break;
- X /*
- X * The following are the keyboard macros
- X * corresponding to the shifted number keys.
- X * (Too many keys... [control] [A] [shift] [1]
- X * is hardly a shortcut!)
- X */
- X case '!':
- X keymac = param->mac_1;
- X break;
- X case '@':
- X keymac = param->mac_2;
- X break;
- X case '#':
- X keymac = param->mac_3;
- X break;
- X case '$':
- X keymac = param->mac_4;
- X break;
- X case '%':
- X keymac = param->mac_5;
- X break;
- X case '^':
- X keymac = param->mac_6;
- X break;
- X case '&':
- X keymac = param->mac_7;
- X break;
- X case '*':
- X keymac = param->mac_8;
- X break;
- X case '(':
- X keymac = param->mac_9;
- X break;
- X case ')':
- X keymac = param->mac_0;
- X break;
- X default:
- X fputc(BEL, stderr);
- X break;
- X }
- X
- X /*
- X * Repaint the stdscr (if we are already talking),
- X * get the stdin/stdout out of the curses mode and
- X * into the terminal mode.
- X */
- X if (fd != -1) {
- X touchwin(stdscr);
- X refresh();
- X }
- X resetterm();
- X term_mode();
- X
- X /*
- X * Some of the output processing options have to be
- X * faked... Unfortunately, adding a LF to CR on
- X * output is one of them.
- X */
- X cr_lf = !strcmp(param->cr_out, "CR/LF");
- X
- X /* run the auto-login script */
- X if (script)
- X do_script(extra_dir);
- X
- X /* re-start input routine */
- X if (input_status)
- X do_input();
- X else
- X suspend(FALSE);
- X
- X /* send the macro */
- X if (*keymac != '\0')
- X send_str(keymac, FAST);
- X /*
- X * If you pressed a key during one of the sleeping
- X * periods (typically the delay to see the status
- X * line change), let the keyboard value fall thru
- X * to the write() below.
- X */
- X if (k == -1)
- X continue;
- X c = k;
- X }
- X /* ignore errors if fd == -1 */
- X write(fd, &c, 1);
- X /* map cr to cr_lf? */
- X if (c == '\r' && cr_lf)
- X write(fd, &lf, 1);
- X }
- X}
- X
- X/*
- X * Fire up the input routine...
- X */
- X
- Xvoid
- Xdo_input()
- X{
- X extern int fd;
- X void error_win();
- X char first[(sizeof(int)*8)+1];
- X#ifdef SHAREDMEM
- X extern int shm_id;
- X#else /* SHAREDMEM */
- X char add_lf[2], log[2], print[2], dup_fd[3];
- X#endif /* SHAREDMEM */
- X /* if no TTY, or already on */
- X if (pid != -1 || fd == -1)
- X return;
- X
- X status->fd = fd;
- X status->add_lf = !strcmp(param->cr_in, "CR/LF");
- X
- X#ifdef SHAREDMEM
- X sprintf(first, "%d", shm_id);
- X#else /* SHAREDMEM */
- X sprintf(first, "%d", status->fd);
- X sprintf(dup_fd, "%d", status->dup_fd);
- X sprintf(add_lf, "%d", status->add_lf);
- X sprintf(log, "%d", status->log);
- X sprintf(print, "%d", status->print);
- X#endif /* SHAREDMEM */
- X
- X /* fork the input routine */
- X if (!(pid = fork())) {
- X#ifdef BSD
- X setpgrp(0, getpid());
- X#else /* BSD */
- X setpgrp();
- X#endif /* BSD */
- X
- X#ifdef SETUGID
- X setuid(getuid());
- X setgid(getgid());
- X#endif /* SETUGID */
- X
- X#ifdef SHAREDMEM
- X execlp("pcomm_input", "pcomm_input", first, (char *) 0);
- X#else /* SHAREDMEM */
- X execlp("pcomm_input", "pcomm_input", first, dup_fd, add_lf,
- X log, print, status->log_path, status->vs_path, (char *) 0);
- X#endif /* SHAREDMEM */
- X error_win(1, "Cannot find (or execute) the 'pcomm_input' program", "");
- X }
- X
- X return;
- X}
- X
- X/*
- X * shut it down...
- X */
- X
- Xvoid
- Xinput_off()
- X{
- X if (pid != -1) {
- X kill(pid, SIGTERM);
- X pid = -1;
- X }
- X return;
- X}
- X
- X/*
- X * Hang up the phone but remain in the Pcomm command state. Uses the
- X * hang_up string only, does *not* drop the DTR!
- X */
- X
- Xvoid
- Xhang_up(verbose)
- Xint verbose;
- X{
- X extern int fd;
- X void send_str(), st_line(), line_set();
- X char buf[80], *strcpy(), *ttyname();
- X /* sanity checking */
- X if (modem == NULL)
- X return;
- X /* anything to hang up? */
- X if (modem->m_cur == -1 || fd == -1)
- X return;
- X
- X if (verbose)
- X st_line("disconnecting");
- X /* special case for OBM */
- X#ifdef UNIXPC
- X if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
- X ioctl(fd, PIOCDISC);
- X /*
- X * The PIOCDISC ioctl screws up the file descriptor!!!
- X * No other phone(7) ioctl can fix it. Whatever it does,
- X * it seems to escape detection with PIOCGETA and TCGETA.
- X * The best I can do is close the port and start over.
- X */
- X strcpy(buf, ttyname(fd));
- X close(fd);
- X fd = open(buf, O_RDWR|O_NDELAY);
- X line_set();
- X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
- X }
- X else
- X#endif /* UNIXPC */
- X send_str(modem->hang_up[modem->m_cur], SLOW);
- X
- X if (verbose)
- X st_line("");
- X return;
- X}
- X
- X/*
- X * Suspend or un-suspend the input routine. The argument is used in
- X * non-shared memory configurations to give the vs_path file a fighting
- X * chance of being written to disk before load_vs() reads it.
- X */
- X
- X/* ARGSUSED */
- Xvoid
- Xsuspend(on)
- Xint on;
- X{
- X unsigned int sleep();
- X
- X if (pid == -1)
- X return;
- X kill(pid, SIGINT);
- X
- X#ifndef SHAREDMEM
- X if (on)
- X sleep(1);
- X#endif /* SHAREDMEM */
- X
- X return;
- X}
- SHAR_EOF
- if test 9863 -ne "`wc -c < 'terminal.c'`"
- then
- echo shar: "error transmitting 'terminal.c'" '(should have been 9863 characters)'
- fi
- fi
- echo shar: "extracting 'tty_att.c'" '(4795 characters)'
- if test -f 'tty_att.c'
- then
- echo shar: "will not over-write existing file 'tty_att.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'tty_att.c'
- X/*
- X * System V specific routines for manipulating the TTY
- X */
- X
- X#include <stdio.h>
- X#include <termio.h>
- X#include <fcntl.h>
- X#include "dial_dir.h"
- X#include "param.h"
- X
- X/*
- X * Change the communication line settings to the new values.
- X */
- X
- Xvoid
- Xline_set()
- X{
- X extern int fd;
- X struct termio tbuf;
- X
- X /*
- X * The manual dial entry also serves to store the previous
- X * line settings. How else would the manual dial entry
- X * know what line setting to use?
- X */
- X if (dir->d_cur != 0) {
- X dir->baud[0] = dir->baud[dir->d_cur];
- X dir->parity[0] = dir->parity[dir->d_cur];
- X dir->dbits[0] = dir->dbits[dir->d_cur];
- X dir->sbits[0] = dir->sbits[dir->d_cur];
- X }
- X /* nothing to do! */
- X if (fd == -1)
- X return;
- X /* get the current settings */
- X ioctl(fd, TCGETA, &tbuf);
- X /* set some beginning values */
- X tbuf.c_cc[4] = 1; /* VMIN */
- X tbuf.c_cc[5] = 0; /* VTIME */
- X tbuf.c_oflag = 0;
- X tbuf.c_iflag = 0;
- X tbuf.c_cflag = (CREAD|HUPCL|CLOCAL);
- X tbuf.c_lflag = 0;
- X
- X if (*param->flow == 'X')
- X tbuf.c_iflag |= (IXON|IXOFF);
- X /* strip high bit? */
- X if (*param->strip == 'Y')
- X tbuf.c_iflag |= ISTRIP;
- X /* the baud rate */
- X switch (dir->baud[dir->d_cur]) {
- X case 300:
- X tbuf.c_cflag |= B300;
- X break;
- X case 1200:
- X tbuf.c_cflag |= B1200;
- X break;
- X case 2400:
- X tbuf.c_cflag |= B2400;
- X break;
- X case 4800:
- X tbuf.c_cflag |= B4800;
- X break;
- X case 9600:
- X tbuf.c_cflag |= B9600;
- X break;
- X case 19200:
- X#ifdef B19200
- X tbuf.c_cflag |= B19200;
- X#else /* B19200 */
- X#ifdef EXTA
- X tbuf.c_cflag |= EXTA;
- X#endif /* EXTA */
- X#endif /* B19200 */
- X break;
- X }
- X /* the parity */
- X switch (dir->parity[dir->d_cur]) {
- X case 'N':
- X break;
- X case 'O':
- X tbuf.c_cflag |= (PARENB|PARODD);
- X break;
- X case 'E':
- X tbuf.c_cflag |= PARENB;
- X break;
- X }
- X /* the data bits */
- X if (dir->dbits[dir->d_cur] == 8)
- X tbuf.c_cflag |= CS8;
- X else
- X tbuf.c_cflag |= CS7;
- X /* the stop bits */
- X if (dir->sbits[dir->d_cur] == 2)
- X tbuf.c_cflag |= CSTOPB;
- X
- X /* now set 'em! */
- X ioctl(fd, TCSETAF, &tbuf);
- X return;
- X}
- X
- X/*
- X * Put the stdin/stdout in terminal mode. We've divided up the
- X * responsibility for the line settings options between the serial port
- X * and the stdin and stdout.
- X */
- X
- Xvoid
- Xterm_mode()
- X{
- X struct termio tbuf;
- X
- X ioctl(0, TCGETA, &tbuf);
- X
- X tbuf.c_cc[4] = 1; /* VMIN */
- X tbuf.c_cc[5] = 0; /* VTIME */
- X tbuf.c_iflag = 0;
- X tbuf.c_oflag = 0;
- X tbuf.c_lflag = 0;
- X /* duplex */
- X if (dir->duplex[dir->d_cur] == 'H')
- X tbuf.c_lflag = ECHO;
- X
- X ioctl(0, TCSETAF, &tbuf);
- X return;
- X}
- X
- X/*
- X * Put the TTY driver in the mode suitable for xmodem transfers.
- X */
- X
- Xvoid
- Xxmodem_mode(fds)
- Xint fds;
- X{
- X struct termio tbuf;
- X
- X ioctl(fds, TCGETA, &tbuf);
- X /*
- X * Turn off the XON/XOFF flow control, turn off echoing, and
- X * switch to 8 bit no parity.
- X */
- X tbuf.c_cc[4] = 1; /* VMIN */
- X tbuf.c_cc[5] = 0; /* VTIME */
- X tbuf.c_iflag = 0; /* no flow control or mapping */
- X tbuf.c_oflag = 0; /* no char mapping or delays */
- X tbuf.c_lflag = 0; /* no echo or signals */
- X tbuf.c_cflag &= ~(PARENB|CSIZE);/* no parity */
- X tbuf.c_cflag |= CS8; /* 8 bit */
- X
- X ioctl(fds, TCSETAF, &tbuf);
- X return;
- X}
- X
- X/*
- X * Put the TTY line in a mode suitable for the ASCII transfer. Puts the
- X * terminal in the raw, non-blocking mode.
- X */
- X
- Xvoid
- Xascii_mode(up)
- Xint up;
- X{
- X extern int fd;
- X struct termio tbuf;
- X
- X ioctl(fd, TCGETA, &tbuf);
- X tbuf.c_oflag = 0;
- X /* flow control & 8th bit stripping */
- X if (up) {
- X tbuf.c_iflag = (ISTRIP|IXON);
- X
- X /* if no CR's, use NL delays */
- X if (!strcmp(param->cr_up, "STRIP"))
- X tbuf.c_oflag = (OPOST|ONLRET);
- X
- X /* CR delay times */
- X switch (param->cr_delay) {
- X case 0:
- X break;
- X case 100:
- X tbuf.c_oflag |= (OPOST|CR2);
- X break;
- X case 150:
- X tbuf.c_oflag |= (OPOST|CR3);
- X break;
- X }
- X }
- X /* if down loading */
- X else
- X tbuf.c_iflag = (ISTRIP|IXOFF);
- X
- X ioctl(fd, TCSETAF, &tbuf);
- X return;
- X}
- X
- X/*
- X * Flush the file descriptor
- X */
- X
- Xint
- Xtty_flush(fds, mode)
- Xint fds, mode;
- X{
- X return(ioctl(fds, TCFLSH, mode));
- X}
- X
- X/*
- X * Wait for the output to drain
- X */
- X
- Xint
- Xtty_drain(fds)
- Xint fds;
- X{
- X return(ioctl(fds, TCSBRK, 1));
- X}
- X
- X/*
- X * Send a modem break
- X */
- X
- Xint
- Xtty_break(fds)
- Xint fds;
- X{
- X return(ioctl(fds, TCSBRK, 0));
- X}
- X
- X/*
- X * Fix the file descriptor so that a read is satisfied immediately. When
- X * read() is called it returns the character in the queue, or an error if
- X * no key was pressed.
- X */
- X
- Xint
- Xtty_noblock(fds, on)
- Xint fds, on;
- X{
- X int current;
- X
- X current = fcntl(fds, F_GETFL, 0);
- X if (on)
- X return(fcntl(fds, F_SETFL, current | O_NDELAY));
- X else
- X return(fcntl(fds, F_SETFL, current & ~O_NDELAY));
- X}
- X
- X/*
- X * Get the current baud rate of the terminal
- X */
- X
- Xint
- Xmy_speed()
- X{
- X static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
- X 1200, 1800, 2400, 4800, 9600, 19200};
- X struct termio tbuf;
- X
- X ioctl(0, TCGETA, &tbuf);
- X return(speed[tbuf.c_cflag & CBAUD]);
- X}
- SHAR_EOF
- if test 4795 -ne "`wc -c < 'tty_att.c'`"
- then
- echo shar: "error transmitting 'tty_att.c'" '(should have been 4795 characters)'
- fi
- fi
- echo shar: "extracting 'tty_ucb.c'" '(4666 characters)'
- if test -f 'tty_ucb.c'
- then
- echo shar: "will not over-write existing file 'tty_ucb.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'tty_ucb.c'
- X/*
- X * Berkeley specific routines for manipulating the TTY
- X */
- X
- X#include <stdio.h>
- X#include <sgtty.h>
- X#include <fcntl.h>
- X#include "dial_dir.h"
- X#include "param.h"
- X
- X/*
- X * Change the communication line settings to the new values.
- X */
- X
- Xvoid
- Xline_set()
- X{
- X extern int fd;
- X struct sgttyb tbuf;
- X
- X /*
- X * The manual dial entry also serves to store the previous
- X * line settings. How else would the manual dial entry
- X * know what line setting to use?
- X */
- X if (dir->d_cur != 0) {
- X dir->baud[0] = dir->baud[dir->d_cur];
- X dir->parity[0] = dir->parity[dir->d_cur];
- X dir->dbits[0] = dir->dbits[dir->d_cur];
- X dir->sbits[0] = dir->sbits[dir->d_cur];
- X }
- X /* nothing to do! */
- X if (fd == -1)
- X return;
- X /* get the current settings */
- X ioctl(fd, TIOCGETP, &tbuf);
- X /* set some beginning values */
- X tbuf.sg_flags = CBREAK;
- X
- X if (*param->flow == 'X')
- X tbuf.sg_flags |= TANDEM;
- X /* the baud rate */
- X switch (dir->baud[dir->d_cur]) {
- X case 300:
- X tbuf.sg_ispeed = B300;
- X tbuf.sg_ospeed = B300;
- X break;
- X case 1200:
- X tbuf.sg_ispeed = B1200;
- X tbuf.sg_ospeed = B1200;
- X break;
- X case 2400:
- X tbuf.sg_ispeed = B2400;
- X tbuf.sg_ospeed = B2400;
- X break;
- X case 4800:
- X tbuf.sg_ispeed = B4800;
- X tbuf.sg_ospeed = B4800;
- X break;
- X case 9600:
- X tbuf.sg_ispeed = B9600;
- X tbuf.sg_ospeed = B9600;
- X break;
- X case 19200:
- X#ifdef B19200
- X tbuf.sg_ispeed = B19200;
- X tbuf.sg_ospeed = B19200;
- X#else /* B19200 */
- X#ifdef EXTA
- X tbuf.sg_ispeed = EXTA;
- X tbuf.sg_ospeed = EXTA;
- X#endif /* EXTA */
- X#endif /* B19200 */
- X break;
- X }
- X /* the parity */
- X switch (dir->parity[dir->d_cur]) {
- X case 'N':
- X tbuf.sg_flags |= ANYP;
- X break;
- X case 'O':
- X tbuf.sg_flags |= ODDP;
- X break;
- X case 'E':
- X tbuf.sg_flags |= EVENP;
- X break;
- X }
- X /* now set 'em! */
- X ioctl(fd, TIOCSETP, &tbuf);
- X return;
- X}
- X
- X/*
- X * Put the stdin/stdout in terminal mode. We've divided up the
- X * responsibility for the line settings options between the serial port
- X * and the stdin and stdout.
- X */
- X
- Xvoid
- Xterm_mode()
- X{
- X struct sgttyb tbuf;
- X
- X ioctl(0, TIOCGETP, &tbuf);
- X
- X tbuf.sg_flags |= CBREAK;
- X tbuf.sg_flags &= ~(RAW|CRMOD|ECHO);
- X
- X if (dir->duplex[dir->d_cur] == 'H')
- X tbuf.sg_flags |= ECHO;
- X
- X ioctl(0, TIOCSETP, &tbuf);
- X return;
- X}
- X
- X/*
- X * Put the TTY driver in the mode suitable for xmodem transfers.
- X */
- X
- Xvoid
- Xxmodem_mode(fds)
- Xint fds;
- X{
- X struct sgttyb tbuf;
- X
- X ioctl(fds, TIOCGETP, &tbuf);
- X /*
- X * Turn off the XON/XOFF flow control, turn off echoing, and
- X * switch to 8 bit no parity.
- X */
- X tbuf.sg_flags |= (RAW|ANYP);
- X tbuf.sg_flags &= ~ECHO;
- X ioctl(fds, TIOCSETP, &tbuf);
- X return;
- X}
- X
- X/*
- X * Put the TTY line in a mode suitable for the ASCII transfer.
- X */
- X
- Xvoid
- Xascii_mode(up)
- Xint up;
- X{
- X extern int fd;
- X struct sgttyb tbuf;
- X
- X ioctl(fd, TIOCGETP, &tbuf);
- X
- X tbuf.sg_flags |= (CBREAK|TANDEM);
- X tbuf.sg_flags &= ~(RAW|CRMOD|ECHO|CRDELAY);
- X
- X if (up) {
- X /* CR delay times */
- X switch (param->cr_delay) {
- X case 0:
- X break;
- X case 100:
- X tbuf.sg_flags |= CR1;
- X break;
- X case 150:
- X tbuf.sg_flags |= CR2;
- X break;
- X }
- X }
- X
- X ioctl(fd, TIOCSETP, &tbuf);
- X return;
- X}
- X
- X/*
- X * Flush the file descriptor. Very messy... flushing the input causes a
- X * wait for the ouput to drain, and there is no output flushing.
- X */
- X
- Xint
- Xtty_flush(fds, mode)
- Xint fds, mode;
- X{
- X int ret_code = 0;
- X struct sgttyb tbuf;
- X
- X switch(mode) {
- X case 0: /* flush input queue */
- X ioctl(fds, TIOCGETP, &tbuf);
- X ioctl(fds, TIOCSETP, &tbuf);
- X break;
- X case 1: /* flush output queue */
- X /* sorry! */
- X break;
- X case 2: /* flush both input and output */
- X ioctl(fds, TIOCFLUSH, 0);
- X break;
- X default:
- X ret_code++;
- X break;
- X }
- X return(ret_code);
- X}
- X
- X/*
- X * Wait for the output to drain
- X */
- X
- Xint
- Xtty_drain(fds)
- Xint fds;
- X{
- X struct sgttyb tbuf;
- X /* this flushes the input too */
- X ioctl(fds, TIOCGETP, &tbuf);
- X return(ioctl(fds, TIOCSETP, &tbuf));
- X}
- X
- X/*
- X * Send a modem break
- X */
- X
- Xint
- Xtty_break(fds)
- Xint fds;
- X{
- X unsigned int sleep();
- X
- X ioctl(fds, TIOCSBRK, (struct sgttyb *) 0);
- X sleep(1);
- X return(ioctl(fds, TIOCCBRK, (struct sgttyb *) 0));
- X}
- X
- X/*
- X * Fix the file descriptor so that a read is satisfied immediately. When
- X * read() is called it returns the character in the queue, or an error if
- X * no key was pressed.
- X */
- X
- Xint
- Xtty_noblock(fds, on)
- Xint fds, on;
- X{
- X int current;
- X
- X current = fcntl(fds, F_GETFL, 0);
- X if (on)
- X return(fcntl(fds, F_SETFL, current | FNDELAY));
- X else
- X return(fcntl(fds, F_SETFL, current & ~FNDELAY));
- X}
- X
- X/*
- X * Get the current baud rate of the terminal
- X */
- X
- Xint
- Xmy_speed()
- X{
- X static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
- X 1200, 1800, 2400, 4800, 9600, 19200};
- X struct sgttyb tbuf;
- X
- X ioctl(0, TIOCGETP, &tbuf);
- X return(speed[tbuf.sg_ispeed]);
- X}
- SHAR_EOF
- if test 4666 -ne "`wc -c < 'tty_ucb.c'`"
- then
- echo shar: "error transmitting 'tty_ucb.c'" '(should have been 4666 characters)'
- fi
- fi
- echo shar: "extracting 'vcs.c'" '(10939 characters)'
- if test -f 'vcs.c'
- then
- echo shar: "will not over-write existing file 'vcs.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'vcs.c'
- X/*
- X * Routines for VCS detection.
- X */
- X
- X#include <stdio.h>
- X#include "config.h"
- X#include "vcs.h"
- X
- X#ifndef OLDCURSES
- X#include <curses.h>
- X#include <term.h>
- X#endif /* OLDCURSES */
- X
- Xstatic int putc_cnt;
- Xstatic char putc_buf[VCS_SIZE];
- X
- X/*
- X * Test for possible VCS (video command sequence). A character return
- X * code means no match. An return code greater than 255 means a VCS
- X * was found.
- X */
- X
- Xint
- Xvcs_filter(c)
- Xchar c;
- X{
- X extern int vcs_codes[NUM_VCS][VCS_SIZE], vcs_leadin[NUM_VCS];
- X extern int num_leadin;
- X static int vcs_buf[VCS_SIZE];
- X static int ptr = 0;
- X register int i;
- X int maybe, possible;
- X
- X /* see if possible */
- X possible = 0;
- X if (ptr == 0) {
- X /*
- X * This is kinda crude... I'm checking to see if the
- X * lead-in character is greater than the space character.
- X * If so, it most probably is NOT a VCS.
- X */
- X if (c >= ' ')
- X return(c & 0xff);
- X /* check the list */
- X for (i=0; i<num_leadin; i++) {
- X if (c == vcs_leadin[i]) {
- X possible++;
- X break;
- X }
- X }
- X if (!possible)
- X return(c & 0xff);
- X }
- X
- X /* build the string */
- X vcs_buf[ptr++] = c;
- X vcs_buf[ptr] = -1;
- X /* test for match */
- X maybe = 0;
- X for (i=0; i<NUM_VCS; i++) {
- X switch (match_codes(vcs_buf, vcs_codes[i], i)) {
- X case YES:
- X ptr = 0;
- X return(i+256);
- X case NO:
- X break;
- X case MAYBE:
- X maybe++;
- X break;
- X }
- X }
- X /* abandon what you've got */
- X if (maybe && ptr == VCS_SIZE-1) {
- X ptr = 0;
- X return(c & 0xff);
- X }
- X /* hang on, wait and see */
- X if (maybe)
- X return(MAYBE);
- X /* a clean miss */
- X ptr = 0;
- X return(c & 0xff);
- X}
- X
- X/*
- X * See if the two integer arrays "match". Character parameters are
- X * designated by codes > 1000 and ASCII digit parameters are designated
- X * by codes > 2000. Uses a simple linear search, so if NUM_VCS grows
- X * this routine will have to mature a bit.
- X */
- X
- Xstatic int
- Xmatch_codes(test, code, k)
- Xint test[], code[], k;
- X{
- X extern int vcs_param[NUM_VCS][5];
- X register int i, j;
- X int pos, done;
- X /* doesn't exist */
- X if (code[0] == -1)
- X return(NO);
- X
- X i = 0;
- X j = 0;
- X while (i<VCS_SIZE && j<VCS_SIZE) {
- X /* at the end (a match) */
- X if (test[i] == -1 && code[j] == -1)
- X return(YES);
- X /* ran out of input */
- X if (test[i] == -1)
- X break;
- X /*
- X * The char parameter (code 1000) always matches the
- X * next character.
- X */
- X if (code[j] >= 1000 && code[j] < 2000) {
- X pos = code[j] -1000;
- X vcs_param[k][pos] = test[i];
- X i++;
- X j++;
- X continue;
- X }
- X /*
- X * The digit parameter (code 2000) tries to match as many
- X * ASCII digits as it can.
- X */
- X if (code[j] >= 2000) {
- X pos = code[j] -2000;
- X /* done with this number? */
- X if (vcs_param[k][pos])
- X done = 1;
- X else
- X done = 0;
- X /* only digits */
- X while (test[i] >= 48 && test[i] <= 57) {
- X if (!done)
- X vcs_param[k][pos] = (vcs_param[k][pos] * 10) + test[i] -48;
- X i++;
- X }
- X /* ended in a digit */
- X if (test[i] == -1 && code[j+1] != -1) {
- X vcs_param[k][pos] = 0;
- X break;
- X }
- X j++;
- X continue;
- X }
- X /* a clean miss */
- X if (test[i] != code[j]) {
- X for (j=0; j<5; j++)
- X vcs_param[k][j] = 0;
- X return(NO);
- X }
- X i++;
- X j++;
- X }
- X /* a maybe */
- X return(MAYBE);
- X}
- X
- X/*
- X * Build the table of VCS codes. Actually we cheat... We tell curses(3)
- X * to build the strings to perform the function, and then we decipher
- X * what it did.
- X *
- X * For example: On a vt100 the cursor motion string in terminfo is:
- X * cup=\E[%i%p1%d;%p2%dH$<5>
- X *
- X * This gets translated to the integer array vcs_code[] as:
- X * \E [ %p1%d ; %p2%d H
- X * 27, 91, 2000, 59, 2001, 72
- X *
- X * Notice that the "%p1" and "%p2" parameters get translated to 2000 and
- X * 2001. This is to signify that the parameters are multiple digit ASCII
- X * encoded numbers. The "%i" and "%d" codes are imbedded into the vcs_opt[]
- X * array in somewhat of a loose manner. In other words, there is no set
- X * format for the vcs_opt[] array. The padding info "$<5>" is ignored.
- X */
- X
- Xvoid
- Xvcs_table()
- X{
- X extern int vcs_codes[NUM_VCS][VCS_SIZE], vcs_opt[NUM_VCS][10];
- X extern int vcs_leadin[NUM_VCS], num_leadin, max_row, max_col;
- X int i, j, k, match, temp[VCS_SIZE];
- X char *p, *strcpy(), buf[VCS_SIZE], *getenv(), *tparm();
- X void fake_it();
- X
- X#ifdef OLDCURSES
- X char tcbuf[1024], tb[1024], *t, *cursor_home, *clr_eol, *clr_eos;
- X char *clear_screen, *cursor_up, *cursor_down, *cursor_right;
- X char *cursor_left, *cursor_address, *getenv(), *tgetstr(), *tgoto();
- X
- X tgetent(tb, getenv("TERM"));
- X t = tcbuf;
- X
- X cursor_home = tgetstr("ho", &t);
- X clr_eol = tgetstr("ce", &t);
- X clr_eos = tgetstr("cd", &t);
- X clear_screen = tgetstr("cl", &t);
- X cursor_up = tgetstr("up", &t);
- X cursor_down = tgetstr("do", &t);
- X cursor_right = tgetstr("nd", &t);
- X cursor_left = tgetstr("le", &t);
- X cursor_address = tgetstr("cm", &t);
- X max_row = tgetnum("li");
- X max_col = tgetnum("co");
- X#else /* OLDCURSES */
- X setupterm(getenv("TERM"), 1, &i);
- X max_row = lines;
- X max_col = columns;
- X#endif /* OLDCURSES */
- X
- X /*
- X * Do the easy ones first. These don't take positional parameters,
- X * so all we have to do is strip the padding info.
- X */
- X for (i=0; i<NUM_VCS; i++) {
- X switch (i) {
- X case HOME:
- X p = cursor_home;
- X break;
- X case CLR_EOL:
- X p = clr_eol;
- X break;
- X case CLR_EOS:
- X p = clr_eos;
- X break;
- X case CLEAR:
- X p = clear_screen;
- X break;
- X case MV_UP:
- X p = cursor_up;
- X break;
- X case MV_DOWN:
- X p = cursor_down;
- X break;
- X case MV_RIGHT:
- X p = cursor_right;
- X break;
- X case MV_LEFT:
- X p = cursor_left;
- X break;
- X default:
- X p = "";
- X break;
- X }
- X /*
- X * Either the capability doesn't exist, or we're gonna
- X * do this one by hand (i.e.: ones with positional parameters)
- X */
- X if (!p) {
- X vcs_codes[i][0] = -1;
- X continue;
- X }
- X /* fake an "output" */
- X fake_it(p);
- X /* copy what it did */
- X j = 0;
- X while (putc_buf[j]) {
- X vcs_codes[i][j] = putc_buf[j];
- X j++;
- X if (j == VCS_SIZE-1)
- X break;
- X }
- X vcs_codes[i][j] = -1;
- X }
- X
- X /*
- X * And now for the difficult ones. The way it's done is: load the
- X * string with a few known parameters and then find where the
- X * parameters end up. The vcs_opt[][] array is "free-flowing"
- X * and means something only to the routine being used.
- X */
- X /* add one to the param */
- X if (substr(cursor_address, "%i") > 0)
- X vcs_opt[MV_DIRECT][0] = 1;
- X /* decimal codes used */
- X if (substr(cursor_address, "%d") > 0)
- X vcs_opt[MV_DIRECT][1] = 1;
- X /* character codes used */
- X if (substr(cursor_address, "%c") > 0)
- X vcs_opt[MV_DIRECT][2] = 1;
- X /* add an offset */
- X if (substr(cursor_address, "%+") > 0)
- X vcs_opt[MV_DIRECT][3] = 1;
- X /* subtract an offset */
- X if (substr(cursor_address, "%-") > 0)
- X vcs_opt[MV_DIRECT][4] = 1;
- X /* load with parameters 12 & 34 */
- X#ifdef OLDCURSES
- X fake_it(tgoto(cursor_address, 12, 34));
- X#else /* OLDCURSES */
- X fake_it(tparm(cursor_address, 12, 34));
- X#endif /* OLDCURSES */
- X
- X j = 0;
- X while (putc_buf[j]) {
- X temp[j] = putc_buf[j];
- X j++;
- X if (j == VCS_SIZE-1)
- X break;
- X }
- X temp[j] = -1;
- X /* if decimal parameters */
- X if (vcs_opt[MV_DIRECT][1]) {
- X /* if add one */
- X if (vcs_opt[MV_DIRECT][0])
- X strcpy(buf, "13");
- X else
- X strcpy(buf, "12");
- X /* where is the 12 (or 13)? */
- X if ((i = substr(putc_buf, buf)) > 0) {
- X temp[i] = 2000;
- X temp[i+1] = -2;
- X }
- X else
- X temp[0] = -1;
- X /* if add one */
- X if (vcs_opt[MV_DIRECT][0])
- X strcpy(buf, "35");
- X else
- X strcpy(buf, "34");
- X /* where is the 34 (or 35)? */
- X if ((i = substr(putc_buf, buf)) > 0) {
- X temp[i] = 2001;
- X temp[i+1] = -2;
- X }
- X else
- X temp[0] = -1;
- X }
- X /* if character parameters */
- X if (vcs_opt[MV_DIRECT][2]) {
- X /* original with 12 and 34 */
- X strcpy(buf, putc_buf);
- X /* change 12 to 13 */
- X#ifdef OLDCURSES
- X fake_it(tgoto(cursor_address, 13, 34));
- X#else /* OLDCURSES */
- X fake_it(tparm(cursor_address, 13, 34));
- X#endif /* OLDCURSES */
- X /* where are they different */
- X i = 0;
- X while (buf[i] != '\0') {
- X if (buf[i] != putc_buf[i])
- X break;
- X i++;
- X }
- X /* sanity checking */
- X if (buf[i] == '\0')
- X temp[0] = -1;
- X /* if add, what is offset? */
- X if (vcs_opt[MV_DIRECT][3])
- X vcs_opt[MV_DIRECT][5] = temp[i] - 13;
- X
- X /* if subtract, what is offset? */
- X if (vcs_opt[MV_DIRECT][4])
- X vcs_opt[MV_DIRECT][5] = 13 - temp[i];
- X
- X temp[i] = 1000;
- X /* change 34 to 35 */
- X#ifdef OLDCURSES
- X fake_it(tgoto(cursor_address, 12, 35));
- X#else /* OLDCURSES */
- X fake_it(tparm(cursor_address, 12, 35));
- X#endif /* OLDCURSES */
- X /* where are they different */
- X i = 0;
- X while (buf[i] != '\0') {
- X if (buf[i] != putc_buf[i])
- X break;
- X i++;
- X }
- X temp[i] = 1001;
- X if (buf[i] == '\0')
- X temp[0] = -1;
- X }
- X /* strip the -2's out, if any */
- X i = 0;
- X j = 0;
- X while (temp[i] != -1) {
- X if (temp[i] != -2)
- X vcs_codes[MV_DIRECT][j++] = temp[i];
- X i++;
- X }
- X vcs_codes[MV_DIRECT][j] = -1;
- X
- X /*
- X * Simplify the list. Some codes are already handled by the
- X * virtual screen routines... no need to duplicate them.
- X */
- X if (vcs_codes[MV_DOWN][0] == '\n')
- X vcs_codes[MV_DOWN][0] = -1;
- X
- X if (vcs_codes[MV_LEFT][0] == 8)
- X vcs_codes[MV_LEFT][0] = -1;
- X
- X /*
- X * Often the "clear screen" sequence will contain the "home"
- X * sequence... if so, don't duplicate the "home" portion.
- X */
- X fake_it(cursor_home);
- X strcpy(buf, putc_buf);
- X
- X fake_it(clear_screen);
- X /* if "home" inside "clear screen" */
- X if ((k = substr(putc_buf, buf)) >= 0) {
- X /* if at the beginning */
- X if (k == 0) {
- X i = 0;
- X for (j=strlen(buf); j<VCS_SIZE; j++)
- X vcs_codes[CLEAR][i++] = putc_buf[j];
- X vcs_codes[CLEAR][i] = -1;
- X }
- X /* if at the end */
- X else if (strlen(buf)+k == strlen(putc_buf))
- X vcs_codes[CLEAR][k] = -1;
- X }
- X /* is "clear screen" still unique */
- X k = 0;
- X for (i=0; i<NUM_VCS; i++) {
- X if (vcs_codes[CLEAR][i] == -1 || vcs_codes[CLR_EOS][i] == -1)
- X break;
- X if (vcs_codes[CLEAR][i] != vcs_codes[CLR_EOS][i]) {
- X k++;
- X break;
- X }
- X }
- X if (k == 0)
- X vcs_codes[CLEAR][0] = -1;
- X
- X /*
- X * Make a list of unique lead-in characters to be used as a
- X * simple hash table.
- X */
- X num_leadin = 0;
- X for (i=0; i<NUM_VCS; i++) {
- X if (vcs_codes[i][0] == -1)
- X continue;
- X /* add any new lead-in character */
- X match = 0;
- X for (j=0; j<num_leadin; j++) {
- X if (vcs_leadin[j] == vcs_codes[i][0])
- X match++;
- X }
- X if (!match)
- X vcs_leadin[num_leadin++] = vcs_codes[i][0];
- X }
- X return;
- X}
- X
- X/*
- X * The routine that fakes curses(3) into outputting the string info with
- X * the padding removed.
- X */
- Xstatic void
- Xfake_it(s)
- Xchar *s;
- X{
- X int fake_putc();
- X
- X putc_cnt = 0;
- X putc_buf[0] = '\0';
- X tputs(s, 1, fake_putc);
- X putc_buf[putc_cnt] = '\0';
- X return;
- X}
- Xstatic int
- Xfake_putc(c)
- Xchar c;
- X{
- X if (c != '\0')
- X putc_buf[putc_cnt++] = c;
- X return(c);
- X}
- X
- X/*
- X * Is string2 contained in string1? If so, return the offset, otherwise
- X * return a -1.
- X */
- X
- Xstatic int
- Xsubstr(s1, s2)
- Xchar *s1, *s2;
- X{
- X int i, len;
- X
- X len = strlen(s2);
- X /* not possible */
- X if (len > strlen(s1))
- X return(-1);
- X
- X i = 0;
- X while (*s1) {
- X if (!strncmp(s1, s2, len))
- X return(i);
- X s1++;
- X i++;
- X }
- X return(-1);
- X}
- SHAR_EOF
- if test 10939 -ne "`wc -c < 'vcs.c'`"
- then
- echo shar: "error transmitting 'vcs.c'" '(should have been 10939 characters)'
- fi
- fi
- echo shar: "extracting 'vcs.h'" '(330 characters)'
- if test -f 'vcs.h'
- then
- echo shar: "will not over-write existing file 'vcs.h'"
- else
- sed 's/^X//' << \SHAR_EOF > 'vcs.h'
- X/*
- X * Definitions to support the detection of video command sequences
- X */
- X
- X#define VCS_SIZE 25
- X#define NUM_VCS 9
- X
- X#define HOME 0
- X#define CLR_EOL 1
- X#define CLR_EOS 2
- X#define CLEAR 3
- X#define MV_UP 4
- X#define MV_DOWN 5
- X#define MV_RIGHT 6
- X#define MV_LEFT 7
- X#define MV_DIRECT 8
- X
- X#define YES 1
- X#define NO 0
- X#define MAYBE (-1)
- SHAR_EOF
- if test 330 -ne "`wc -c < 'vcs.h'`"
- then
- echo shar: "error transmitting 'vcs.h'" '(should have been 330 characters)'
- fi
- fi
- echo shar: "extracting 'waitfor.c'" '(2108 characters)'
- if test -f 'waitfor.c'
- then
- echo shar: "will not over-write existing file 'waitfor.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'waitfor.c'
- X/*
- X * Wait for a string on the stdin. Returns a 0 on success, 1 on failure
- X * and -1 on error. This is an external program designed to be used in
- X * shell scripts.
- X */
- X
- X#define TIMEOUT 10
- X#define BUF_SIZ 1024
- X#define HZ 60
- X#define STRSTR
- X
- Xint wf_flag;
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/times.h>
- X
- X#ifdef BSD
- X#include <setjmp.h>
- Xjmp_buf wf_buf;
- X#endif /* BSD */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i, j, timeout;
- X char c, buf[BUF_SIZ], *string, *strstr();
- X struct tms t;
- X long t1;
- X void exit();
- X
- X if (argc < 2 || argc > 3) {
- X fprintf(stderr, "Usage: waitfor -n string\n");
- X exit(-1);
- X }
- X
- X if (argv[1][0] == '-') {
- X timeout = atoi(&argv[1][1]);
- X if (argc != 3) {
- X fprintf(stderr, "Usage: waitfor -n string\n");
- X exit(-1);
- X }
- X string = argv[2];
- X }
- X else {
- X timeout = TIMEOUT;
- X string = argv[1];
- X }
- X /* here we go.. */
- X i = 0;
- X t1 = times(&t);
- X while ((times(&t) - t1) < (HZ * timeout)) {
- X if ((j = getc_line()) != -1) {
- X c = j & 0x7f;
- X /* no NULLs please */
- X if (c != '\0') {
- X buf[i++] = c;
- X buf[i] = '\0';
- X }
- X
- X if (i >= BUF_SIZ) {
- X fprintf(stderr, "waitfor: buffer overflow\n");
- X exit(-1);
- X }
- X /* yea.. we found it! */
- X if (strstr(buf, string))
- X exit(0);
- X }
- X }
- X exit(1);
- X}
- X
- Xint
- Xgetc_line()
- X{
- X int wf_force();
- X char c;
- X unsigned int alarm();
- X
- X signal(SIGALRM, wf_force);
- X wf_flag = 0;
- X
- X alarm(1);
- X
- X#ifdef BSD
- X if (setjmp(wf_buf))
- X return(-1);
- X#endif /* BSD */
- X
- X if (read(0, &c, 1) <= 0) {
- X alarm(0);
- X return(-1);
- X }
- X if (wf_flag)
- X return(-1);
- X alarm(0);
- X return(c & 0xff);
- X}
- X
- X/* ARGSUSED */
- Xstatic int
- Xwf_force(dummy)
- Xint dummy;
- X{
- X#ifdef BSD
- X longjmp(wf_buf, 1);
- X#else /* BSD */
- X signal(SIGALRM, wf_force);
- X wf_flag = 1;
- X#endif /* BSD */
- X}
- X
- X#ifdef STRSTR
- X/*
- X * Return a pointer to the first occurance of string str2 in str1.
- X * Returns a NULL if str2 is not in str1.
- X */
- X
- Xchar *
- Xstrstr(str1, str2)
- Xchar *str1, *str2;
- X{
- X int len;
- X len = strlen(str2);
- X while (*str1) {
- X if (*str2 == *str1) {
- X if (!strncmp(str2, str1, len))
- X return(str1);
- X }
- X str1++;
- X }
- X return(NULL);
- X}
- X#endif /* STRSTR */
- SHAR_EOF
- if test 2108 -ne "`wc -c < 'waitfor.c'`"
- then
- echo shar: "error transmitting 'waitfor.c'" '(should have been 2108 characters)'
- fi
- fi
- echo shar: "extracting 'x_ascii.c'" '(6450 characters)'
- if test -f 'x_ascii.c'
- then
- echo shar: "will not over-write existing file 'x_ascii.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'x_ascii.c'
- X/*
- X * Transfer a file using just XON/XOFF flow control. Currently limited to
- X * 7 bit ASCII codes. (If this causes too much trouble, I'll change it).
- X */
- X
- X#include <stdio.h>
- X#include <curses.h>
- X#include <signal.h>
- X#include "config.h"
- X#include "misc.h"
- X#include "param.h"
- X
- X#ifdef BSD
- X#include <setjmp.h>
- Xjmp_buf bl_buf;
- X#endif /* BSD */
- X
- Xvoid
- Xxfer_ascii(list, up)
- Xchar *list;
- Xint up;
- X{
- X int cr_lf;
- X char *file, *strtok();
- X void send_ascii(), rcv_ascii(), line_set(), st_line(), suspend();
- X void load_vs(), ascii_mode(), input_off(), term_mode();
- X unsigned int sleep();
- X
- X touchwin(stdscr);
- X refresh();
- X /* only one file from list */
- X file = strtok(list, " \t");
- X
- X cr_lf = !strcmp(param->cr_out, "CR/LF");
- X ascii_mode(up);
- X /* out of curses mode */
- X resetterm();
- X term_mode();
- X tty_noblock(0, TRUE);
- X
- X if (up) {
- X /* un-suspend the input routine */
- X suspend(FALSE);
- X send_ascii(file, cr_lf);
- X suspend(TRUE);
- X }
- X else {
- X input_off();
- X rcv_ascii(file, cr_lf);
- X }
- X
- X /*
- X * Restoring the TTY modes is easier than setting them... The
- X * fixterm() and line_set() routines fix most of the damage.
- X */
- X line_set();
- X fixterm();
- X tty_noblock(0, FALSE);
- X
- X /*
- X * On downloading, the contents of the virtual screen won't contain
- X * the characters shown during the transfer. Too bad...
- X */
- X load_vs();
- X beep();
- X st_line("xfer complete");
- X
- X sleep(2);
- X return;
- X}
- X
- X/*
- X * Send a file. The local echo option is independent of the duplex option,
- X * and would very rarely be used since the characters are most likely
- X * being echoed on the screen anyway.
- X */
- X
- Xstatic void
- Xsend_ascii(file, cr_lf)
- Xchar *file;
- Xint cr_lf;
- X{
- X extern int fd;
- X FILE *fp, *my_fopen();
- X int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace;
- X char buf[80];
- X unsigned char c, last;
- X unsigned int sleep();
- X void error_win();
- X /* permission already checked */
- X if (!(fp = my_fopen(file, "r"))) {
- X sprintf(buf, "\"%s\"", file);
- X error_win(0, "Can't open file for read", buf);
- X return;
- X }
- X /* ASCII transfer options */
- X strip_cr = !strcmp(param->cr_up, "STRIP");
- X add_lf = !strcmp(param->cr_up, "ADD LF");
- X strip_lf = !strcmp(param->lf_up, "STRIP");
- X add_cr = !strcmp(param->lf_up, "ADD CR");
- X expand = !strcmp(param->expand, "YES");
- X lecho = !strcmp(param->lecho, "YES");
- X pace = !strcmp(param->pace, "YES");
- X
- X last = 0;
- X while ((i = fgetc(fp)) != EOF) {
- X /* any keyboard activity? */
- X switch (j = getchar()) {
- X case -1: /* no key was pressed */
- X break;
- X case ESC: /* <ESC> key for abort */
- X fclose(fp);
- X sleep(2);
- X tty_drain(fd);
- X return;
- X default: /* send the char */
- X c = j;
- X putc_line(c);
- X if (c == '\r' && cr_lf)
- X putc_line('\n');
- X break;
- X }
- X c = i & 0x7f;
- X /* expand blank lines */
- X if (expand && last == '\n' && c == '\n')
- X putc_line(' ');
- X last = c;
- X
- X /* CR translations */
- X if (c == '\r' && strip_cr)
- X continue;
- X if (c == '\r' && add_lf) {
- X putc_line(c);
- X putc_line('\n');
- X continue;
- X }
- X /* LF translations */
- X if (c == '\n' && strip_lf)
- X continue;
- X if (c == '\n' && add_cr) {
- X putc_line('\r');
- X putc_line(c);
- X continue;
- X }
- X putc_line(c);
- X /*
- X * There's really no mechanism for delaying characters
- X * going to the output, so we fake it by waiting for
- X * each character to clear the I/O buffer.
- X */
- X if (pace)
- X tty_drain(fd);
- X if (lecho) {
- X putchar((char) c);
- X fflush(stdout);
- X }
- X }
- X fclose(fp);
- X sleep(2);
- X tty_drain(fd);
- X return;
- X}
- X
- X/*
- X * Receive a file. The timer is used to end the transfer. This is not
- X * that much different from the data logging option. The use of bgetc_line()
- X * and non-blocking input makes it seem like full duplex, but it's not.
- X * Be aware that while the timer is active the keyboard is deaf. Input is
- X * NOT loaded into the virtual screen!!
- X */
- X
- Xstatic void
- Xrcv_ascii(file, cr_lf)
- Xchar *file;
- Xint cr_lf;
- X{
- X FILE *fp, *my_fopen();
- X int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
- X unsigned int delay;
- X char c, buf[80];
- X void error_win();
- X /* permission already checked */
- X if (!(fp = my_fopen(file, "w"))) {
- X sprintf(buf, "\"%s\"", file);
- X error_win(0, "Can't open file for write", buf);
- X return;
- X }
- X /* ASCII transfer options */
- X strip_cr = !strcmp(param->cr_dn, "STRIP");
- X add_lf = !strcmp(param->cr_dn, "ADD LF");
- X strip_lf = !strcmp(param->lf_dn, "STRIP");
- X add_cr = !strcmp(param->lf_dn, "ADD CR");
- X
- X got_first = 0;
- X delay = 1;
- X while (1) {
- X /* keyboard activity */
- X switch (i = getchar()) {
- X case -1: /* no key was pressed */
- X break;
- X case ESC: /* <ESC> key */
- X fclose(fp);
- X return;
- X default: /* send it */
- X c = i;
- X putc_line((unsigned char) c);
- X if (c == '\r' && cr_lf)
- X putc_line('\n');
- X break;
- X }
- X /* read a character */
- X if ((i = bgetc_line(delay)) == -1) {
- X /*
- X * The transfer timeout is not activated until the
- X * first character is received. Until then, it polls
- X * the line for one second and loops backs for
- X * keyboard input.
- X */
- X if (got_first) {
- X fclose(fp);
- X return;
- X }
- X continue;
- X }
- X got_first = 1;
- X delay = param->timer;
- X c = i & 0x7f;
- X /* display it on the screen */
- X putchar(c);
- X fflush(stdout);
- X /* CR translations */
- X if (c == '\r' && strip_cr)
- X continue;
- X if (c == '\r' && add_lf) {
- X fputc(c, fp);
- X fputc('\n', fp);
- X continue;
- X }
- X /* LF translations */
- X if (c == '\n' && strip_lf)
- X continue;
- X if (c == '\n' && add_cr) {
- X fputc('\r', fp);
- X fputc(c, fp);
- X continue;
- X }
- X fputc(c, fp);
- X }
- X}
- X
- X/*
- X * Get a character from the line (using buffered I/O) with a specified
- X * time-out period in seconds. If the function times-out, it returns a -1.
- X */
- X
- Xstatic int bl_flag;
- X
- Xstatic int
- Xbgetc_line(sec)
- Xunsigned int sec;
- X{
- X int c, bl_force();
- X unsigned int alarm();
- X
- X signal(SIGALRM, bl_force);
- X bl_flag = 0;
- X
- X alarm(sec);
- X
- X#ifdef BSD
- X if (setjmp(bl_buf))
- X return(-1);
- X#endif /* BSD */
- X
- X if ((c = buf_read()) < 0) {
- X alarm(0);
- X return(-1);
- X }
- X if (bl_flag)
- X return(-1);
- X alarm(0);
- X return(c);
- X}
- X
- X/* ARGSUSED */
- Xstatic int
- Xbl_force(dummy)
- Xint dummy;
- X{
- X#ifdef BSD
- X longjmp(bl_buf, 1);
- X#else /* BSD */
- X signal(SIGALRM, bl_force);
- X bl_flag = 1;
- X#endif /* BSD */
- X}
- X
- X/*
- X * Do a single character buffered read from the serial port.
- X */
- X
- Xstatic int
- Xbuf_read()
- X{
- X extern int fd;
- X static char buf[CLIST_SIZ];
- X static char *bufp = buf;
- X static int n = 0;
- X
- X if (n <= 0) {
- X n = read(fd, buf, CLIST_SIZ);
- X bufp = buf;
- X }
- X if (--n >= 0)
- X return(*bufp++ & 0xff);
- X return(-1);
- X}
- SHAR_EOF
- if test 6450 -ne "`wc -c < 'x_ascii.c'`"
- then
- echo shar: "error transmitting 'x_ascii.c'" '(should have been 6450 characters)'
- fi
- fi
- echo shar: "extracting 'x_batch.c'" '(8686 characters)'
- if test -f 'x_batch.c'
- then
- echo shar: "will not over-write existing file 'x_batch.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'x_batch.c'
- X/*
- X * Routines to support the batch protocols.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <curses.h>
- X#include "config.h"
- X#include "misc.h"
- X#include "xmodem.h"
- X
- X/*
- X * Send the file name for the modem7 batch. Only uses 11 characters
- X * of the filename. Returns zero on success or the standard error codes.
- X */
- X
- Xint
- Xsend_modem7(win, name)
- XWINDOW *win;
- Xchar *name;
- X{
- X char *new_name, *fix_name();
- X unsigned char sum, calc_sum();
- X
- X /* convert to 11 character name */
- X new_name = fix_name(name);
- X sum = calc_sum((unsigned char *) new_name, 12);
- X
- X putc_line(ACK);
- X /* for each character in the name */
- X while (*new_name != CTRLZ) {
- X putc_line((unsigned char) *new_name);
- X
- X switch (getc_line(3)) {
- X case -1: /* timed out */
- X clear_line(win, 12, 24, TRUE);
- X waddstr(win, "NO RESPONSE");
- X wrefresh(win);
- X return(ERROR);
- X case ACK: /* got it! */
- X break;
- X case CAN: /* cancel transmission */
- X if (getc_line(2) == CAN) {
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "REMOTE ABORTED");
- X wrefresh(win);
- X return(CANCEL);
- X }
- X /* fall thru... */
- X default:
- X clear_line(win, 12, 24, TRUE);
- X waddstr(win, "NAME FAILED");
- X wrefresh(win);
- X return(ERROR);
- X }
- X new_name++;
- X }
- X putc_line(CTRLZ);
- X /* verify the checksum */
- X if (getc_line(10) != sum) {
- X putc_line('u');
- X clear_line(win, 12, 24, TRUE);
- X waddstr(win, "CHECKSUM FAILED");
- X wrefresh(win);
- X return(ERROR);
- X }
- X putc_line(ACK);
- X return(0);
- X}
- X
- X/*
- X * Receive a modem7 file name. Returns zero on success, the standard error
- X * codes, or a -1 on the end-of-batch. (Oddly enough, the end-of-batch code
- X * is the same as the code for a user abort)
- X */
- X
- Xint
- Xrcv_modem7(win, default_err)
- XWINDOW *win;
- Xint default_err;
- X{
- X extern char file_name[15];
- X int i, j, err_method, err_count, got_it;
- X unsigned char sum, calc_sum();
- X char temp_name[13];
- X void change_name(), unfix_name();
- X
- X err_method = default_err;
- X if (default_err == CRC_CHECKSUM)
- X err_method = CRC;
- X
- X err_count = 0;
- X got_it = 0;
- X while (err_count < MAX_ERRORS) {
- X /* switch to checksum? */
- X if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2)
- X err_method = CHECKSUM;
- X
- X if (err_method == CRC)
- X putc_line('C');
- X else
- X putc_line(NAK);
- X /* what'd we get? */
- X switch (getc_line(10)) {
- X case -1: /* timed out */
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "NO RESPONSE");
- X wrefresh(win);
- X err_count++;
- X case ACK: /* ready to go... */
- X got_it++;
- X break;
- X default: /* huh? */
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "BAD HEADER");
- X wrefresh(win);
- X err_count++;
- X }
- X }
- X if (!got_it)
- X return(ERROR);
- X /* get the name */
- X for (i=0; i<12; i++) {
- X j = getc_line(3);
- X
- X switch (j) {
- X case -1: /* timed out */
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "NO RESPONSE");
- X wrefresh(win);
- X return(ERROR);
- X case EOT: /* end of batch? */
- X return(-1);
- X case CAN: /* cancel transmission */
- X if (getc_line(2) == CAN) {
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "REMOTE ABORTED");
- X wrefresh(win);
- X return(CANCEL);
- X }
- X /* fall thru... */
- X case 'u': /* bad name character */
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "BAD NAME");
- X wrefresh(win);
- X return(ERROR);
- X default: /* the name... */
- X temp_name[i] = j & 0xff;
- X if (j != CTRLZ)
- X putc_line(ACK);
- X break;
- X }
- X }
- X temp_name[12] = '\0';
- X /* send our checksum */
- X sum = calc_sum((unsigned char *) temp_name, 12);
- X putc_line(sum);
- X /* do they agree? */
- X if (getc_line(10) != ACK) {
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "BAD NAME");
- X wrefresh(win);
- X return(ERROR);
- X }
- X /* load the file_name array */
- X unfix_name(temp_name);
- X /* any name collisions? */
- X change_name(win, file_name);
- X return(0);
- X}
- X
- X/*
- X * Send the block 0 information for a ymodem batch transfer. Uses only
- X * the name component of the path and the file size.
- X */
- X
- Xint
- Xsend_ymodem(win, file, size)
- XWINDOW *win;
- Xchar *file;
- Xlong size;
- X{
- X unsigned short crc, calc_crc();
- X char *strcpy(), *memset();
- X unsigned char buf[133];
- X /* start with a clean block */
- X memset(buf, '\0', 133);
- X /* the header */
- X buf[0] = SOH;
- X buf[1] = 0;
- X buf[2] = 255;
- X
- X /*
- X * The block zero consists of the file name (no path component),
- X * a NULL, and the file length (as a string). The end of batch
- X * marker is an empty block.
- X */
- X if (*file != '\0') {
- X strcpy((char *) &buf[3], file);
- X sprintf((char *) &buf[strlen(file)+4], "%ld", size);
- X }
- X /* the crc */
- X crc = calc_crc(&buf[3], 128);
- X buf[131] = crc >> 8;
- X buf[132] = crc;
- X /* the block count */
- X mvwaddstr(win, 7, 24, "0 ");
- X
- X return(send_block(win, buf, 133));
- X}
- X
- X/*
- X * Receive the block 0 information for a ymodem batch transfer. We
- X * only use the file name and the size (if present). Currently doesn't
- X * support full path names.
- X */
- X
- Xint
- Xrcv_ymodem(win)
- XWINDOW *win;
- X{
- X extern unsigned char buf[1029];
- X extern long file_length;
- X extern char file_name[15];
- X int code, length_is_at;
- X long atol();
- X
- X file_length = 0L;
- X file_name[0] = '\0';
- X /* read the zero block */
- X if (code = rcv_block(win, 1, 1024, 0))
- X return(code);
- X /* at end of batch */
- X if (buf[3] == '\0')
- X return(0);
- X /* get the file name */
- X change_name(win, (char *) &buf[3]);
- X /* any trouble? */
- X if (file_name[0] == '\0') {
- X putc_line(CAN);
- X return(0);
- X }
- X /*
- X * The file length is placed after the NULL of the file name
- X * and is terminated by another NULL. If the length is missing,
- X * atol() will see a NULL and return 0.
- X */
- X length_is_at = strlen((char *) &buf[3]) + 4;
- X file_length = atol((char *) &buf[length_is_at]);
- X return(0);
- X}
- X
- X/*
- X * Handle file name collisions. Prepend an "X" to the name until you find
- X * a name that doesn't already exist. Creates a NULL name on error.
- X * Loads the global character array "file_name".
- X */
- X
- Xvoid
- Xchange_name(win, str)
- XWINDOW *win;
- Xchar *str;
- X{
- X extern char file_name[15];
- X register int i;
- X int modified;
- X char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat();
- X unsigned int sleep();
- X /* dissect the name component */
- X if ((s = strrchr(str, '/')))
- X strcpy(temp, ++s);
- X else
- X strcpy(temp, str);
- X
- X strcpy(ans, temp);
- X file_name[0] = '\0';
- X /* write permission on directory? */
- X if (access(".", 2)) {
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY");
- X wrefresh(win);
- X return;
- X }
- X /* prepend up to 13 "X"s */
- X modified = 0;
- X for (i=1; i<14; i++) {
- X if (access(ans, 0)) {
- X if (modified) {
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X waddstr(win, "NAME COLLISION");
- X wrefresh(win);
- X sleep(1);
- X }
- X strcpy(file_name, ans);
- X return;
- X }
- X
- X modified++;
- X strcpy(temp, "X");
- X strncat(temp, ans, 13);
- X temp[14] = '\0';
- X strcpy(ans, temp);
- X }
- X beep();
- X clear_line(win, 12, 24, TRUE);
- X waddstr(win, "BAD NAME");
- X wrefresh(win);
- X return;
- X}
- X
- X/*
- X * Convert a perfectly good Unix file name to fit the CP/M file name
- X * rules. Used for the modem7 batch file transfer. Returns a pointer
- X * to a static area containing the new name.
- X */
- X
- Xchar *
- Xfix_name(path)
- Xchar *path;
- X{
- X int dot;
- X char *s, *name, temp[15], *ext, *strcpy(), *strrchr();
- X static char ans[13];
- X /* ignore the path component */
- X if (s = strrchr(path, '/'))
- X strcpy(temp, ++s);
- X else
- X strcpy(temp, path);
- X name = temp;
- X
- X ext = "";
- X dot = 0;
- X for (s=name; *s; ++s) {
- X if (*s == '.' && !dot) {
- X dot++;
- X *s = '\0';
- X ext = s + 1;
- X }
- X if (islower(*s))
- X *s = toupper(*s);
- X }
- X /* if null name component */
- X if (*name == '\0')
- X name = "X";
- X /* if name too long */
- X if (strlen(name) > 8)
- X *(name+8) = '\0';
- X /* if extension too long */
- X if (strlen(ext) > 3)
- X *(ext+3) = '\0';
- X
- X sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ);
- X return(ans);
- X}
- X
- X/*
- X * Convert a CP/M style filename into a legal Unix file name. Loads the
- X * global character array "file_name".
- X */
- X
- Xvoid
- Xunfix_name(cpm_name)
- Xchar *cpm_name;
- X{
- X extern char file_name[15];
- X register int i, n;
- X int dot;
- X char temp[15];
- X
- X file_name[0] = '\0';
- X if (*cpm_name == '\0')
- X return;
- X
- X strcpy(temp, cpm_name);
- X /* 8 character of the name */
- X n = 0;
- X for (i=0; i<8; i++) {
- X if (temp[i] != ' ') {
- X if (isupper(temp[i]))
- X file_name[n++] = tolower(temp[i]);
- X else
- X file_name[n++] = temp[i];
- X }
- X }
- X /* 3 character extension */
- X dot = 0;
- X for (i=8; i<11; i++) {
- X if (temp[i] != ' ') {
- X if (!dot) {
- X dot++;
- X file_name[n++] = '.';
- X }
- X if (isupper(temp[i]))
- X file_name[n++] = tolower(temp[i]);
- X else
- X file_name[n++] = temp[i];
- X }
- X }
- X file_name[n] = '\0';
- X return;
- X}
- SHAR_EOF
- if test 8686 -ne "`wc -c < 'x_batch.c'`"
- then
- echo shar: "error transmitting 'x_batch.c'" '(should have been 8686 characters)'
- fi
- fi
- echo shar: "extracting 'x_extrnl.c'" '(2965 characters)'
- if test -f 'x_extrnl.c'
- then
- echo shar: "will not over-write existing file 'x_extrnl.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'x_extrnl.c'
- X/*
- X * Spawn a shell with the stdin and stdout swapped with the remote
- X * system, ie:
- X * +----------+
- X * TTYin ------------> stdin | |
- X * | shell |
- X * TTYout <---------- stdout | |
- X * +----------+
- X *
- X * An undocumented feature: The external protocol gateway
- X * can be used to pipe the output of a normal Unix command to the
- X * remote system.
- X */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <curses.h>
- X#include <errno.h>
- X#include "config.h"
- X
- X#ifdef BSD
- X#include <sys/file.h>
- X#else /* BSD */
- X#include <fcntl.h>
- X#endif /* BSD */
- X
- Xvoid
- Xdo_extrnl(cmd)
- Xchar *cmd;
- X{
- X extern int fd, errno;
- X WINDOW *xt_win, *newwin();
- X SIG_TYPE (*istat)(), (*qstat)();
- X int epid, want_out, sig_status;
- X char buf[80], *ttyname(), *strcpy();
- X unsigned int sleep();
- X void _exit(), input_off();
- X
- X input_off();
- X /* a full window */
- X xt_win = newwin(LINES, COLS, 0, 0);
- X touchwin(xt_win);
- X wrefresh(xt_win);
- X /* out of curses mode */
- X resetterm();
- X
- X if (!(epid = fork())) {
- X /* create a new process group ID */
- X#ifdef BSD
- X setpgrp(0, getpid());
- X#else /* BSD */
- X setpgrp();
- X#endif /* BSD */
- X /* recreate the device name */
- X strcpy(buf, ttyname(fd));
- X close(fd);
- X /* swap the stdin */
- X close(0);
- X#ifdef UNIXPC
- X/*
- X * Some strange things here... The OBM uses the second parameter of
- X * open() to determine if the port should be in the DATA mode or
- X * the VOICE mode. Therefore, we must always open with read and write.
- X */
- X if (!strncmp(buf, "/dev/ph", 7))
- X open(buf, O_RDWR);
- X else
- X#endif /* UNIXPC */
- X open(buf, O_RDONLY);
- X /* swap the stdout */
- X close(1);
- X#ifdef UNIXPC
- X if (!strncmp(buf, "/dev/ph", 7))
- X open(buf, O_RDWR);
- X else
- X#endif /* UNIXPC */
- X open(buf, O_WRONLY);
- X#ifdef SETUGID
- X setgid(getgid());
- X setuid(getuid());
- X#endif /* SETUGID */
- X execl("/bin/sh", "sh", "-c", cmd, (char *) 0);
- X _exit(1);
- X }
- X istat = signal(SIGINT, SIG_IGN);
- X qstat = signal(SIGQUIT, SIG_IGN);
- X
- X /*
- X * Check the keyboard while the external program is running. If
- X * the user hits the <ESC> key, then kill the entire process
- X * group associated with the new shell.
- X */
- X want_out = 0;
- X while(1) {
- X switch(wait_key(stdscr, 1)) {
- X case -1: /* timed out */
- X break;
- X case 27: /* a user abort */
- X#ifdef BSD
- X killpg(epid, SIGKILL);
- X#else /* BSD */
- X kill(-epid, SIGKILL);
- X#endif /* BSD */
- X want_out++;
- X break;
- X default:
- X beep();
- X break;
- X }
- X if (want_out)
- X break;
- X /* see if the process it still active */
- X#ifdef BSD
- X if ((kill(epid, 0) == -1) && errno == ESRCH)
- X#else /* BSD */
- X if ((kill(-epid, 0) == -1) && errno == ESRCH)
- X#endif /* BSD */
- X break;
- X }
- X /* wait for the zombie process */
- X wait(&sig_status);
- X
- X signal(SIGINT, istat);
- X signal(SIGQUIT, qstat);
- X /* back to curses mode */
- X sleep(1);
- X fixterm();
- X
- X clearok(curscr, TRUE);
- X werase(xt_win);
- X wrefresh(xt_win);
- X delwin(xt_win);
- X return;
- X}
- SHAR_EOF
- if test 2965 -ne "`wc -c < 'x_extrnl.c'`"
- then
- echo shar: "error transmitting 'x_extrnl.c'" '(should have been 2965 characters)'
- fi
- fi
- exit 0
- # End of shell archive
-
-
-